package com.duqc.util;

import lombok.extern.slf4j.Slf4j;

import java.util.Optional;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName ThreadPoolUtil
 * @Description 线程池
 * @Author duqc
 * @Date 2021/4/7
 **/
@Slf4j
public class ThreadPoolUtil {

    private ThreadPoolUtil(){

    }

    /**
     * 当前CPU核数
     */
    private static final int CPU_NUM = Optional.of(Runtime.getRuntime().availableProcessors()).orElse(5);
    /**
     * 线程缓冲队列(ArrayBlockingQueue是基于数组实现的有界阻塞队列，此队列按先进先出的原则对元素进行排0序。
     * 新元素插入到队列的尾部，获取元素的操作则从队列的头部进行。)
     */
    private static final BlockingQueue<Runnable> BQUEUE = new ArrayBlockingQueue<>(100);
    /**
     * 核心线程数，会一直存活，即使没有任务，线程池也会维护线程的最少数量
     */
    private static final int SIZE_CORE_POOL = CPU_NUM;
    /**
     * 线程池维护线程的最大数量
     */
    private static final int SIZE_MAX_POOL = CPU_NUM * 2;
    /**
     * 线程池维护线程所允许的空闲时间
     */
    private static final long ALIVE_TIME = 2000;

    /**
     * 如果要自定义饱和策略,实现RejectedExecutionHandler接口，重写rejectedExecution()方法即可
     * CallerRunsPolicy，在任务被拒绝添加后，会调用当前线程池的所在的线程去执行被拒绝的任务。
     */
    private static final ThreadPoolExecutor POOL = new ThreadPoolExecutor(
            SIZE_CORE_POOL, SIZE_MAX_POOL, ALIVE_TIME, TimeUnit.MILLISECONDS, BQUEUE, new ThreadPoolExecutor.CallerRunsPolicy());

    static {
        POOL.prestartAllCoreThreads();
    }

    public static ThreadPoolExecutor getPool() {
        log.info(CPU_NUM + "-------------------------");
        return POOL;
    }

}
